home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1998 June / SGI Freeware 1998 June.iso / dist / fw_ATxgopher.idb / usr / freeware / src / xgopher.1.3 / misc.c.z / misc.c
C/C++ Source or Header  |  1998-01-21  |  11KB  |  492 lines

  1. /* misc.c
  2.    miscellaneous utility functions. */
  3.  
  4.      /*---------------------------------------------------------------*/
  5.      /* Xgopher        version 1.3     08 April 1993                  */
  6.      /*                version 1.2     20 November 1992               */
  7.      /*                version 1.1     20 April 1992                  */
  8.      /*                version 1.0     04 March 1992                  */
  9.      /* X window system client for the University of Minnesota        */
  10.      /*                                Internet Gopher System.        */
  11.      /* Allan Tuchman, University of Illinois at Urbana-Champaign     */
  12.      /*                Computing and Communications Services Office   */
  13.      /* Copyright 1992, 1993 by                                       */
  14.      /*           the Board of Trustees of the University of Illinois */
  15.      /* Permission is granted to freely copy and redistribute this    */
  16.      /* software with the copyright notice intact.                    */
  17.      /*---------------------------------------------------------------*/
  18.  
  19.  
  20. #include <stdio.h>
  21. #include <sys/time.h>
  22. #include <ctype.h>
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25.  
  26. #include "conf.h"
  27. #include "gopher.h"
  28. #include "globals.h"
  29. #include "appres.h"
  30. #include "itemList.h"
  31. #include "dirList.h"
  32. #include "misc.h"
  33.  
  34. #include "osdep.h"
  35.  
  36.  
  37. /* timeNow
  38.    return the current time in some useful units, e.g., seconds. */
  39.  
  40. gopherTime
  41. timeNow()
  42. {
  43.     struct timeval    tp;
  44.     struct timezone    tzp;
  45.  
  46.     gettimeofday(&tp, &tzp);
  47.     return tp.tv_sec;
  48. }
  49.  
  50.  
  51.  
  52. /* timeSince
  53.    return the units (e.g., seconds) of time elapsed since the given time. */
  54.  
  55. gopherTime
  56. timeSince(t)
  57. gopherTime    t;
  58. {
  59.     struct timeval    tp;
  60.     struct timezone    tzp;
  61.  
  62.     return (timeNow() - t);
  63. }
  64.  
  65.  
  66. /* setDirTime
  67.    set the creation time field on a gopher directory */
  68.  
  69. void
  70. setDirTime(d)
  71. gopherDirP    d;
  72. {
  73.     d->created = timeNow();
  74.     return;
  75. }
  76.  
  77.  
  78. /* clearDirWhenOld
  79.    cause a directory to be updated if it's creation time was a while ago. */
  80.  
  81. void
  82. clearDirWhenOld(d)
  83. gopherDirP    d;
  84. {
  85.     if (d == NULL  || d == getCurrentDir()) return;
  86.  
  87.     if (d->created == NOT_LOADED) return;
  88.  
  89.     if (timeSince(d->created) > appResources->directoryTime) {
  90.         LOG(logFP, "Freeing old directory: %s\n",
  91.                         USER_STRING(d->selectorItem));
  92.         freeItemList(&(d->contents));
  93.         d->created = NOT_LOADED;
  94.     }
  95.  
  96.     return;
  97. }
  98.  
  99.  
  100. /* getTempFile
  101.    generate a temperary file name and return a pointer to it.
  102.    The caller should check for a NULL file pointer.
  103.    (The Unix routines mktemp(), tmpnam(), or tempnam() could be
  104.    used as the body of this routine.) */
  105.  
  106. void
  107. getTempFile(tempName)
  108. char    *tempName;
  109. {
  110.     static int    fileCount = 0;
  111.     static int    thisPID = 0;
  112.  
  113.     if (thisPID == 0) thisPID = getpid();
  114.     sprintf (tempName, "%s/gop%d.%d",
  115.             tildePath(appResources->tempDirectory),
  116.             thisPID, fileCount++);
  117.  
  118.     return;
  119. }
  120.  
  121.  
  122. /* These symbols are on most, but not all flavors of Unix, usually
  123.    in <sys/stat.h> or <sys/mode.h>.  They are defined here just in
  124.    case they are missing.  The symbols here are the POSIX names. */
  125.  
  126. #ifndef S_IWUSR
  127. #ifdef    S_IWRITE
  128. #define         S_IWUSR S_IWRITE /* write permission, owner */
  129. #else    /* !def S_IWRITE */
  130. #define         S_IWUSR 0000200 /* write permission, owner */
  131. #endif    /* def S_IWRITE */
  132. #endif
  133.  
  134. #ifndef S_IWGRP
  135. #define         S_IWGRP 0000020 /* write permission, group */
  136. #endif
  137.  
  138. #ifndef S_IWOTH
  139. #define         S_IWOTH 0000002 /* write permission, other */
  140. #endif
  141.  
  142.  
  143. /* isWriteableMode
  144.    return true if the given path name is that of an writable directory */
  145.  
  146. BOOLEAN
  147. isWriteableMode(statBuf)
  148. struct stat    *statBuf;
  149. {
  150.     int    myUid, myGid;
  151.  
  152.     if (statBuf->st_mode & S_IWOTH) {
  153.         return TRUE;
  154.     }
  155.  
  156.     myGid = (int) getgid();
  157.     if ((statBuf->st_gid == myGid) && (statBuf->st_mode & S_IWGRP)) {
  158.         return TRUE;
  159.     }
  160.  
  161.     myUid = (int) getuid();
  162.     if (statBuf->st_uid == myUid  &&  statBuf->st_mode & S_IWUSR) {
  163.         return TRUE;
  164.     }
  165.  
  166.     return FALSE;
  167. }
  168.  
  169. /* These symbols are on most, but not all flavors of Unix, usually
  170.    in <sys/stat.h>.  They are defined here just in case they are missing.
  171.    convex doesn't even have S_IEXEC.  */
  172.  
  173. #ifndef S_IEXEC
  174. #define         S_IEXEC 0000100 /* execute/search permission, owner */
  175. #endif
  176.  
  177. #ifndef S_IXGRP
  178. #define         S_IXGRP 0000010 /* execute/search permission, group */
  179. #endif
  180.  
  181. #ifndef S_IXOTH
  182. #define         S_IXOTH 0000001 /* execute/search permission, other */
  183. #endif
  184.  
  185.  
  186. /* isExecutable
  187.    return true if the given path name is that of an executable file */
  188.  
  189. BOOLEAN
  190. isExecutable(pathName)
  191. char    *pathName;
  192. {
  193.     struct stat    buf;
  194.     int    myUid, myGid;
  195.  
  196.     if (stat (pathName, &buf) != 0) return FALSE;
  197.  
  198.     if (buf.st_mode & S_IXOTH) {
  199.         return TRUE;
  200.     }
  201.  
  202.     myGid = (int) getgid();
  203.     if ((buf.st_gid == myGid) && (buf.st_mode & S_IXGRP)) {
  204.         return TRUE;
  205.     }
  206.  
  207.     myUid = (int) getuid();
  208.     if (buf.st_uid == myUid  &&  buf.st_mode & S_IEXEC) {
  209.         return TRUE;
  210.     }
  211.  
  212.     return FALSE;
  213. }
  214.  
  215.  
  216. /* makeWordList
  217.    turn a string of words into a list of words, ignoring reserved words. */
  218.  
  219. char    **
  220. makeWordList(string)
  221. char    *string;
  222. {
  223.     char    *wordSpace;
  224.     char    **word;
  225.     char    *cp;
  226.     char    *wp;
  227.     int    next = 0;
  228.     int    n = 0;
  229.  
  230.     if (string == NULL) return NULL;
  231.  
  232.     if ( ((wordSpace = malloc(INDEX_WORD_LEN)) == NULL)  ||
  233.          ((word = (char **) malloc(INDEX_WORD_COUNT * sizeof(char *))) ==
  234.                               NULL) ) {
  235.       fprintf(stderr,
  236.           "Memory allocation error; trying to make index word list.\n");
  237.       fprintf(stderr,
  238.           "Recovery attempt by ignoring word list.\n");
  239.       return NULL;
  240.     }
  241.  
  242.     cp = string;
  243.     while (*cp != '\0') {
  244.         while ((! isalnum(*cp)) && *cp != '\0' ) cp++;
  245.         if ( *cp == '\0' ) break;
  246.         wp = word[n] = &(wordSpace[next]);
  247.         while ( isalnum(*cp) ) {
  248.             *wp++ = isupper(*cp) ? tolower(*cp) : *cp;
  249.             cp++;
  250.         }
  251.         *wp = '\0';
  252.  
  253.         if ( strcmp( word[n], "and") == 0  ||
  254.              strcmp(word[n], "not") == 0 ||
  255.              strcmp(word[n], "or") == 0) {
  256.             continue;
  257.         }
  258.  
  259.         next = next + strlen( word[n]) + 1;
  260.         n++;
  261.     }
  262.  
  263.  
  264.     if (n == 0) {
  265.         free (wordSpace);
  266.         free (word);
  267.         return NULL;
  268.     }
  269.  
  270.     word[n] = NULL;
  271.     return (word);
  272. }
  273.  
  274.  
  275. /* freeWordList
  276.    free a word list created by makeWordList. */
  277.  
  278. void
  279. freeWordList(list)
  280. char    **list;
  281. {
  282.     if (list != NULL  &&  list[0] != NULL) {
  283.         free (list[0]);
  284.         free (list);
  285.     }
  286. }
  287.  
  288.  
  289. /* nextInPath 
  290.    is an auxiliary function to support cmdPath (below) */
  291.  
  292. static char *
  293. nextInPath (scan)
  294.    char **scan;
  295.    {
  296.       char *pc, *start;
  297.    
  298.       /*---Null scan pointer says we are done---*/
  299.  
  300.       if (*scan == 0) return(0);
  301.    
  302.       /*---Advance scan pointer until ':' or '\0'---*/
  303.  
  304.       for (pc=(*scan); (*pc != ':') &&
  305.              (*pc != '\0'); pc++) ;
  306.    
  307.       /*---Remember where we started---*/
  308.  
  309.       start = *scan;
  310.    
  311.       /*---Did we get to the end of the path string?---*/
  312.  
  313.       if (*pc == '\0') {
  314.          /*---Yes, tell the next time that we're done---*/
  315.          *scan = 0;
  316.       } else {
  317.          /*---No, make the ':' into a NULL (terminates returned string)
  318.              and advance next scan to char after ':'---*/
  319.          *pc = '\0';
  320.          *scan = pc+1;
  321.       }
  322.    
  323.       return (start);
  324.    }
  325.  
  326.  
  327. /* cmdPath
  328.    this code finds the path to an executable program using the user's
  329.    search path.   If an absolute path name is provided, it is used.
  330.    Otherwise, we use envp to find the $PATH environment
  331.    variable; gets its value; then looks for the program name in
  332.    that path.  The absolute path name of the first executable program
  333.    in the path is returned or NULL if none is found with execute
  334.    permission.
  335.    
  336.    This routine is dependent on the Unix operating system.  Mostly
  337.    because the notion of what constitutes an executable file is
  338.    OS specific.  If you have porting problems, you can either rewrite
  339.    this routine or just specify absolute path names everywhere. */
  340.  
  341. char *
  342. cmdPath (pgmName)
  343. char    *pgmName;
  344. {
  345.     /* cmdPath uses stat(2) to look for the executable file by trying
  346.        each directory in the users path.  Each time that fails, try the
  347.        next directory in the path.  The first time it succeeds, return
  348.        the path.  If the name is not found at all in the path, then
  349.        return NULL.  */
  350.  
  351.     char    path[PATH_NAME_LEN], tempbuf[PATH_NAME_LEN];
  352.     char    *scan, *dir;
  353.     char    *name, *pathVar;
  354.     struct stat    buf;
  355.     char    *absPathName = (char *) malloc (PATH_NAME_LEN);
  356.    
  357.     /* according to the man page for sh(1), if the command name
  358.      contains a '/', then the $path variable is not searched. */
  359.    
  360.     if (index (pgmName, '/')) {
  361.         strcpy (absPathName, pgmName);
  362.         return (absPathName);
  363.     } else {
  364.         if (((pathVar = getenv ("PATH")) == NULL)  ||
  365.              (*pathVar == '\0')) {
  366.             strcpy (absPathName, "./");
  367.             strcat (absPathName, pgmName);
  368.             return (absPathName);
  369.         }
  370.         strncpy (path, pathVar, PATH_NAME_LEN);
  371.         *absPathName = '\0';
  372.    
  373.         scan = path;
  374.  
  375.         while( (dir = nextInPath (&scan)) != 0 ) {
  376.             strncpy (tempbuf, dir, PATH_NAME_LEN);
  377.             strcat (tempbuf, "/");
  378.             name = strcat (tempbuf, pgmName);
  379.  
  380.             if (isExecutable(name)) {
  381.                 strcpy (absPathName, name);
  382.                 return (absPathName);
  383.             }
  384.         }
  385.         return (NULL);
  386.     }
  387. }
  388.  
  389.  
  390. #include <pwd.h>
  391. /* tildePath
  392.    expand a leading "~/" on a pathname to be the value of $HOME/.
  393.    The value returned is a pointer to static storage and must
  394.    be copied by the caller to preserve it.   If there is no leading "~/",
  395.    then the input pathname is copied to the static storage. */
  396.  
  397. char *
  398. tildePath(path)
  399. char    *path;
  400. {
  401.     char        *home;
  402.     static char    newPath[PATH_NAME_LEN];
  403.  
  404.     *newPath = '\0';
  405.  
  406.     if (path != NULL) {
  407.         if (*path == '~') {
  408.             if (*(path+1) == '/'  ||  *(path+1) == NULLC) {
  409.             if ((home = getenv("HOME")) != NULL) {
  410.                 strcpy(newPath, home);
  411.             }
  412.             path++;
  413.         } else {
  414.             char *slash = index (path+1, '/');
  415.             struct passwd   *pwdentry;
  416.             if (slash != NULL) {
  417.             *slash = '\0';
  418.                 if ((pwdentry = getpwnam(path+1)) != NULL) {
  419.                 strcpy(newPath, pwdentry->pw_dir);
  420.                 path = slash;
  421.                 }
  422.             *slash = '/';
  423.             } else {
  424.                 if ((pwdentry = getpwnam(path+1)) != NULL) {
  425.                 strcpy(newPath, pwdentry->pw_dir);
  426.                 path += strlen(path);
  427.                 }
  428.             }
  429.         }
  430.         }
  431.         strcat(newPath, path);
  432.     }
  433.  
  434.     return newPath;
  435. }
  436.  
  437.  
  438.  
  439.  
  440.  
  441. /* vStringSet
  442.    set the value of a variable length string, length and data.
  443.  
  444.    This routine was inspired by those in STRstring.* from the
  445.    gopher Unix client, version 0.9.  The main reason for changing
  446.    them at all is that the chosen data type name in the original
  447.    routines, String, conflicts with the X Window System data
  448.    type of the same name, but different type.
  449.  
  450.    For our purposes it is not worth allocating less than 128
  451.    bytes.  The primary use is for selector strings.  These will 
  452.    generally grow , but eventually stabalize around 100 bytes.
  453.    Except for WAIS searches, when they will grow REALLY big. */
  454.  
  455. void vStringSet(vs, value)
  456. vString *vs;
  457. char    *value;
  458. {
  459.     int    need;
  460.  
  461.     if (value == NULL) return;
  462.  
  463.     if (*value == '\0') 
  464.         need = 1;
  465.     else
  466.         need = strlen(value) + 1;
  467.     
  468.     if (vs->data == NULL) {
  469.         if (need < 128) need = 128;
  470.         if ((vs->data = malloc (need * sizeof(char *))) == NULL) {
  471.             fprintf (stderr,
  472.                 "Cannot allocate more memory for a string.");
  473.             exit(1);
  474.         }
  475.         strcpy (vs->data, value);
  476.         vs->len = need;
  477.     } else {
  478.         if (vs->len >= need)
  479.             strcpy(vs->data, value);
  480.         else {
  481.             if ((vs->data = realloc(vs->data, need)) == NULL) {
  482.                 fprintf (stderr,
  483.                   "Cannot allocate more memory for a string.");
  484.                 exit(1);
  485.             }
  486.  
  487.             strcpy(vs->data, value);
  488.             vs->len = need;
  489.         }
  490.     }
  491. }
  492.